package com.google.code.motoo.codec.http;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.code.motoo.codec.CumulativeProtocolDecoder;
import com.google.code.motoo.codec.ProtocolDecoderOutput;
import com.google.code.motoo.codec.textline.LineDelimiter;
import com.google.code.motoo.core.IoBuffer;
import com.google.code.motoo.core.IoSession;

/**
 * 
 * firefox:
 * 
 * 
 * @author linfengqi
 * @since java 1.5
 * @date 2009-12-22
 */
public class HttpDecoder extends CumulativeProtocolDecoder {
	
	public final static Log log = LogFactory.getLog(HttpDecoder.class);
	
	/** The message encoding. */
    public String charset;
	private static byte[] header_delimit = "\r\n\r\n".getBytes();
	
	private final static int CONTENT_START_OFFSET = 4;
	private final static int CONTENT_END_LENGTH = " HTTP/1.1".length();
	private static byte[] delimiter;
	
	public HttpDecoder(String charset, LineDelimiter delimiter) {
		this.charset = charset;
		this.delimiter = delimiter.getValue().getBytes();
	}

	@Override
	protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
		if (in.hasRemaining()) {
			int initPosition = in.position();
			while(in.hasRemaining()) {
				byte b = in.get();
				if (b == header_delimit[0]) {
					int position = in.position();
					boolean match = true;
					for (int i = 1; i < header_delimit.length; i++) {
						if (header_delimit[i] != in.get()) {
							match = false;
							break;
						}
					}

					if (match) {
						byte[] source = in.array();
						int contentOffset = initPosition + CONTENT_START_OFFSET;
						int contentSize = contentEnd(source) - CONTENT_END_LENGTH - contentOffset;
						out.write(new String(source, contentOffset, contentSize, charset));
			            
						return true;
					} else {
						in.position(position);
					}
				}
				
			}
		}
		return false;
	}
	
	private int contentEnd(byte[] data) {
		for (int i = 0; i < data.length; i++) {
			if (data[i] == delimiter[0]) {
				boolean isMatch = true;
				for (int j = 1; j < delimiter.length; j++) {
					if (data[i + j] != delimiter[j]) {
						isMatch = false;
						break;
					}
				}
				if (isMatch) {
					return i;
				}
			}
		}

		return 0;
	}

	public void dispose(IoSession session) throws Exception {

	}

	public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception {

	}

}
